package com.zzedu.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zzedu.common.annotation.DataScope;
import com.zzedu.common.utils.NextWeekdayUtils;
import com.zzedu.common.utils.StringUtils;
import com.zzedu.domain.ZzCourse;
import com.zzedu.domain.ZzPictureBook;
import com.zzedu.domain.ZzTimetable;
import com.zzedu.dto.ZzTimetableDTO;
import com.zzedu.enmuns.ClzzTypeEnums;
import com.zzedu.mapper.ZzTimetableMapper;
import com.zzedu.params.ZzClassesParams;
import com.zzedu.service.IZzCourseService;
import com.zzedu.service.IZzPictureBookService;
import com.zzedu.service.IZzTimetableService;
import com.zzedu.vo.TimetableVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * (教育-校区)班级课程Service业务层处理
 *
 * @author Mr.Wang
 * @date 2025-06-05
 */
@Service
public class ZzTimetableServiceImpl extends ServiceImpl<ZzTimetableMapper, ZzTimetable> implements IZzTimetableService {

    @Autowired
    IZzPictureBookService zzPictureBookService;

    @Autowired
    IZzCourseService zzCourseService;

    @Override
    public LambdaQueryWrapper<ZzTimetable> buildQuery(ZzTimetableDTO zzTimetable) {
        LambdaQueryWrapper<ZzTimetable> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(null != zzTimetable.getClzzId(), ZzTimetable::getClzzId, zzTimetable.getClzzId());
        lambdaQueryWrapper.eq(null != zzTimetable.getBookId(), ZzTimetable::getBookId, zzTimetable.getBookId());
        lambdaQueryWrapper.eq(null != zzTimetable.getStudyDate(), ZzTimetable::getStudyDate, zzTimetable.getStudyDate());
        lambdaQueryWrapper.eq(null != zzTimetable.getSortNo(), ZzTimetable::getSortNo, zzTimetable.getSortNo());
        lambdaQueryWrapper.orderByAsc(ZzTimetable::getStudyDate).orderByAsc(ZzTimetable::getId);
        return lambdaQueryWrapper;
    }

    @Override
    public List<TimetableVO> buildTimetable(ZzClassesParams zzClassesParams) {
        LocalDate openDate = zzClassesParams.getOpenDate();
        if (openDate == null || CollectionUtils.isEmpty(zzClassesParams.getCourseIdArray()) || null == zzClassesParams.getClzzType()) {
            return Lists.newArrayList();
        }
        LocalDateTime openDateTime = LocalDateTime.of(openDate, LocalTime.MIN);
        List<ZzPictureBook> zzPictureBookList = Lists.newArrayList();
        ClzzTypeEnums clzzTypeEnums = ClzzTypeEnums.getCode(zzClassesParams.getClzzType());
        if (ClzzTypeEnums.ROUTINE == clzzTypeEnums) {
            Assert.isTrue(zzClassesParams.getCourseIdArray().size() < 13, "常规班不能超过12个UNIT");
        } else {
            Assert.isTrue(zzClassesParams.getCourseIdArray().size() < 3, "特殊班不能超过2个UNIT");
        }
        List<ZzCourse> zzCourseList = this.zzCourseService.list(Wrappers.lambdaQuery(ZzCourse.class).in(ZzCourse::getId, zzClassesParams.getCourseIdArray()).orderByAsc(ZzCourse::getSortNo));
        Map<Long, String> courseName = Maps.newHashMap();
        for (ZzCourse zzCourse : zzCourseList) {
            List<ZzPictureBook> pictureBookList = this.zzPictureBookService.list(Wrappers.lambdaQuery(ZzPictureBook.class).eq(ZzPictureBook::getUnitId, zzCourse.getId())
                    .orderByAsc(ZzPictureBook::getSortNo)
            )
                    ;
            if (CollectionUtils.isNotEmpty(pictureBookList)) {
                zzPictureBookList.addAll(pictureBookList);
            }
            courseName.put(zzCourse.getId(), zzCourse.getName());
        }
        List<LocalDateTime> resultTime;
        int size = zzPictureBookList.size();

        if (ClzzTypeEnums.ROUTINE == clzzTypeEnums) {
            //周期
            int count = size % zzClassesParams.getFrequency() == 0 ? size / zzClassesParams.getFrequency() : size / zzClassesParams.getFrequency() + 1;
            List<DayOfWeek> targetDaysOfWeek = Lists.newArrayList();
            if (StringUtils.isNotBlank(zzClassesParams.getWeekTime1())) {
                targetDaysOfWeek.add(DayOfWeek.of(Integer.parseInt(zzClassesParams.getWeekTime1())));
            }
            if (StringUtils.isNotBlank(zzClassesParams.getWeekTime2())) {
                targetDaysOfWeek.add(DayOfWeek.of(Integer.parseInt(zzClassesParams.getWeekTime2())));
            }
            resultTime = NextWeekdayUtils.findWeeklyGroupsAsSingleList(openDateTime, targetDaysOfWeek, count);
        } else {
            resultTime = Lists.newArrayList();
            for (int i = 0; i < size; i++) {
                resultTime.add(openDateTime.plusDays(i));
            }
        }

        AtomicInteger index = new AtomicInteger();
        return Optional.ofNullable(zzPictureBookList).orElse(Lists.newArrayList()).stream().map(zzPictureBook -> {
            int sortNo =index.incrementAndGet();
            TimetableVO timetableVO = new TimetableVO();
            timetableVO.setUnitName(MapUtils.getString(courseName, zzPictureBook.getUnitId(), ""));
            timetableVO.setId(zzPictureBook.getId());
            timetableVO.setName(zzPictureBook.getName());

            timetableVO.setSortNo(sortNo);
            timetableVO.setLearnTime(zzClassesParams.getLearnTime());
            if (ClzzTypeEnums.ROUTINE == clzzTypeEnums) {
                if (1 == zzClassesParams.getFrequency()) {
                    timetableVO.setLearnTime(zzClassesParams.getClassTime1());
                } else {
                    if (timetableVO.getSortNo() % 2 == 0) {
                        timetableVO.setLearnTime(zzClassesParams.getClassTime2());
                    } else {
                        timetableVO.setLearnTime(zzClassesParams.getClassTime1());
                    }
                }
            }
            timetableVO.setStudyTime(resultTime.get(--sortNo));
            return timetableVO;
        }).collect(Collectors.toList());
    }

    @DataScope(otherIdColumnName = "school_id")
    public <E extends IPage<ZzTimetable>> E page(E page, Wrapper<ZzTimetable> queryWrapper) {
        return super.page(page, queryWrapper);
    }

    @Override
    @DataScope(otherIdColumnName = "school_id")
    public List<ZzTimetable> list(IPage<ZzTimetable> page, Wrapper<ZzTimetable> queryWrapper) {
        return super.list(page, queryWrapper);
    }

    @Override
    @DataScope(otherIdColumnName = "school_id")
    public ZzTimetable getById(Serializable id) {
        return super.getById(id);
    }

    @Override
    @DataScope(otherIdColumnName = "school_id")
    public boolean updateById(ZzTimetable entity) {
        return super.updateById(entity);
    }

    @Override
    public List<TimetableVO> convertVO(List<ZzTimetable> zzTimetableList) {
        List<TimetableVO> timetableVOList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(zzTimetableList)) {
            for (ZzTimetable zzTimetable : zzTimetableList) {
                ZzPictureBook zzPictureBook = zzPictureBookService.getById(zzTimetable.getBookId());
                TimetableVO timetableVO = new TimetableVO();
                timetableVO.setStudyTime(zzTimetable.getStudyDate());
                timetableVO.setId(zzTimetable.getId());
                timetableVO.setName(zzPictureBook.getName());
                timetableVO.setSortNo(zzTimetable.getSortNo());
                ZzCourse zzCourse = this.zzCourseService.getById(zzPictureBook.getUnitId());
                if (null != zzCourse) {
                    timetableVO.setUnitName(zzCourse.getName());
                } else {
                    timetableVO.setUnitName("该UNIT已被删除");
                }
                timetableVO.setLearnTime(new String[]{zzTimetable.getStartDate(), zzTimetable.getEndDate()});
                timetableVOList.add(timetableVO);
            }
        }
        return timetableVOList;
    }
    public boolean hasTimeConflict(List<ZzTimetable> listA, List<ZzTimetable> listB) {
        for (ZzTimetable a : listA) {
            for (ZzTimetable b : listB) {
                if (isTimeConflict(a, b)) {
                    return true; // 存在冲突
                }
            }
        }
        return false; // 没有冲突
    }
    private boolean isTimeConflict(ZzTimetable course1, ZzTimetable course2) {
        String[] hours = course1.getEndDate().split(":");
        LocalDateTime start1 = course1.getStudyDate();
        LocalDateTime end1 = start1.withHour(Integer.parseInt(hours[0])).withMinute(Integer.parseInt(hours[1]));
        LocalDateTime start2 = course2.getStudyDate();
        hours = course2.getEndDate().split(":");
        LocalDateTime end2 = start2.withHour(Integer.parseInt(hours[0])).withMinute(Integer.parseInt(hours[1]));
        // 判断是否时间交叉
        return start1.isBefore(end2) && start2.isBefore(end1);
    }

}